package de.nabble.model;

import java.awt.Graphics2D;

import de.nabble.gui.Paintable;

public class GameBoard implements Paintable {
	
	
	public static final int WIDTH = 15;
	public static final int HEIGHT = 15;
	
	private Field[][] board;

	/**
	 * Constructs a new Gameboard with all fields inclusive the special fields.
	 */
	public GameBoard() {
		board = new Field[WIDTH][HEIGHT];
		createBoard();
	}
	
	/**
	 * Tests if a letter has no neighbours on the gameboard.
	 * @param l the letter to check
	 * @param x the x coordinate
	 * @param y the y coordinate
	 * @return true if the letter has no neighbours.
	 * TODO isLetterAlone() noch einbinden
	 */
	public  boolean isLetterAlone(int x, int y) {
		int max = board.length;
		
		if(x > max || y > max || x < 0 || y < 0)
			throw new IndexOutOfBoundsException();
		
		if(x == 0 && y == 0) {
			return board[x][y + 1].getLetter() == null 
										&& board[x + 1][y].getLetter() == null;
			
		} else if(x == max - 1 && y == max - 1) {
			return board[x][y - 1].getLetter() == null 
										&& board[x - 1][y].getLetter() == null;
			
		} else if(x == 0 && y < max - 1 && y > 0) {
			return board[x][y + 1].getLetter() == null 
										&& board[x][y - 1].getLetter() == null
										&& board[x + 1][y].getLetter() == null;
			
		} else if(y == 0 && x < max - 1 && x > 0) {
			return board[x + 1][y].getLetter() == null
										&& board[x - 1][y].getLetter() == null
										&& board[x][y + 1].getLetter() == null;
			
		} else if(x < max - 1 && x > 0 && y < max - 1 && y > 0) {
			return board[x][y + 1].getLetter() == null
										&& board[x + 1][y].getLetter() == null
										&& board[x][y - 1].getLetter() == null
										&& board[x - 1][y].getLetter() == null;
		}
		
		return false;
	}
	
	/**
	 * Puts the given letter on the board.
	 * @param letter the letter to put on the board.
	 * @param x the x coordinate of the target field.
	 * @param y the y coordinate of the target field.
	 */
	public void setLetterOnField(Letter letter, int x, int y) {
		if(letter == null || x < 0 || y < 0 || x >= WIDTH || y >= HEIGHT) {
			throw new IllegalArgumentException("One argument is illegal. Values: " 
					+ letter.toString() + " " + x + " " + y);
		}
		board[x][y].setLetter(letter);
	}
	
	public Letter getLetter(int x, int y) {
		return board[x][y].getLetter();
	}
	
	public Field[][] getFields() {
		return board;
	}
	
	/**
	 * Creates the whole board with the special fields.
	 */
	private void createBoard() {
		for(int i = 0; i < WIDTH; i++) {
			for(int j = 0; j < HEIGHT; j++) {
				board[i][j] = new Field();
			}
		}
		
		setTripleWordWorthinessFields();
		setDoubleWordWorthinessFields();
		
		setTripleLetterWorthinessFields();
		setDoubleLetterWorthinessFields();
	}
	
	/**
	 * creates the fields with triple letterworthiness.
	 */
	private void setTripleLetterWorthinessFields() {
		board[5][1].setLetterWorthiness(3);
		board[9][1].setLetterWorthiness(3);
		
		board[1][5].setLetterWorthiness(3);
		board[5][5].setLetterWorthiness(3);
		board[9][5].setLetterWorthiness(3);
		board[13][5].setLetterWorthiness(3);
		
		board[1][9].setLetterWorthiness(3);
		board[5][9].setLetterWorthiness(3);
		board[9][9].setLetterWorthiness(3);
		board[13][9].setLetterWorthiness(3);
		
		board[5][HEIGHT - 2].setLetterWorthiness(3);
		board[9][HEIGHT - 2].setLetterWorthiness(3);
	}
	
	/**
	 * creates the fields with double letterworthiness.
	 */
	private void setDoubleLetterWorthinessFields() {
		board[0][3].setLetterWorthiness(2);
		board[0][11].setLetterWorthiness(2);
		board[3][0].setLetterWorthiness(2);
		board[11][0].setLetterWorthiness(2);
		board[HEIGHT - 1][3].setLetterWorthiness(2);
		board[HEIGHT - 1][11].setLetterWorthiness(2);
		board[3][WIDTH - 1].setLetterWorthiness(2);
		board[11][WIDTH - 1].setLetterWorthiness(2);
		
		board[2][6].setLetterWorthiness(2);
		board[2][8].setLetterWorthiness(2);
		board[3][7].setLetterWorthiness(2);
		
		board[6][WIDTH - 3].setLetterWorthiness(2);
		board[7][WIDTH - 4].setLetterWorthiness(2);
		board[8][WIDTH - 3].setLetterWorthiness(2);
		
		board[11][WIDTH / 2].setLetterWorthiness(2);
		board[12][WIDTH / 2 - 1].setLetterWorthiness(2);
		board[12][WIDTH / 2 + 1].setLetterWorthiness(2);
		
		board[6][2].setLetterWorthiness(2);
		board[7][3].setLetterWorthiness(2);
		board[8][2].setLetterWorthiness(2);
		
		board[6][6].setLetterWorthiness(2);
		board[8][6].setLetterWorthiness(2);
		board[6][8].setLetterWorthiness(2);
		board[8][8].setLetterWorthiness(2);
	}
	
	/**
	 * creates the fields with triple wordworthiness
	 */
	private void setTripleWordWorthinessFields() {
		for(int i = 0; i < WIDTH; i++) {
			for(int j = 0; j < HEIGHT; j++) {
				if(j == 0 || j == WIDTH - 1) {
					if(i == WIDTH / 2 || i == WIDTH - 1 || i == 0) {
						board[i][j].setWordWorthiness(Field.TRIPLE_WORD_WORTHINESS);					
					}
				}
				
				if((i == 0 || i == WIDTH - 1) && j == HEIGHT / 2) {
					board[i][j].setWordWorthiness(Field.TRIPLE_WORD_WORTHINESS);
				}
			}
		}
	}
	
	/**
	 * Creates the fields with double wordworthiness
	 */
	private void setDoubleWordWorthinessFields() {
		int j = 1;
		for(int i = 1; i < 5; i++) {
			board[i][j++].setWordWorthiness(Field.DOUBLE_WORD_WORTHINESS);
		}
		
		j = 10;
		for(int i = 10; i < 14; i++) {
			board[i][j++].setWordWorthiness(Field.DOUBLE_WORD_WORTHINESS);
		}

		j = 13;
		for(int i = 1; i < 5; i++) {
			board[i][j--].setWordWorthiness(Field.DOUBLE_WORD_WORTHINESS);
		}
		
		j = 13;
		for(int i = 1; i < 5; i++) {
			board[j--][i].setWordWorthiness(Field.DOUBLE_WORD_WORTHINESS);
		}
		
		board[WIDTH / 2][HEIGHT / 2].setWordWorthiness(Field.DOUBLE_WORD_WORTHINESS);
	}
	
	@Override
	public String toString() {
		String s = "\n";
		for(Field[] fa : board) {
			for(Field f : fa) {
				s += f + " ";
			}
			s += "\n";
		}		
		return s;
	}
	
	@Override
	public void paint(Graphics2D g) {

	}

	public int getWidth() {
		return WIDTH;
	}
	
	public int getHeight() {
		return HEIGHT;
	}

}
